package com.yss.reportworld.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.spring.PropertyPreFilters;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.yss.common.core.constant.RequestDataHelper;
import com.yss.common.core.domain.TreeNode;
import com.yss.common.core.enums.YssStatusEnum;
import com.yss.common.core.enums.YssYseNoEnum;
import com.yss.common.core.exception.BusinessException;
import com.yss.common.core.utils.DateUtils;
import com.yss.common.core.utils.StringUtils;
import com.yss.common.core.utils.uuid.IdUtils;
import com.yss.common.security.utils.SecurityUtils;
import com.yss.reportworld.domain.*;
import com.yss.reportworld.enums.ReportWorldEnum;
import com.yss.reportworld.mapper.DataCustomerMapper;
import com.yss.reportworld.mapper.DataModularMapper;
import com.yss.reportworld.mapper.DataReportMapper;
import com.yss.reportworld.service.*;
import com.yss.reportworld.util.TableInfoUtil;
import lombok.extern.slf4j.Slf4j;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yss.reportworld.mapper.CustomerMapper;
import org.springframework.transaction.annotation.Transactional;

/**
 * 客户信息Service业务层处理
 *
 * @author yss
 * @date 2023-03-24
 */
@Slf4j
@Service
public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> implements ICustomerService {
    @Autowired
    private IDataCustomerService dataCustomerService;
    @Autowired
    private IDataModularService dataModularService;
    @Autowired
    private IDataReportService dataReportService;
    @Autowired
    private IWeComService weComService;

    /**
     * 查询客户信息列表
     *
     * @param customer 客户信息
     * @return 客户信息
     */
    @Override
    public List<Customer> selectCustomerList(Customer customer) {
        try {
            TableInfoUtil.handleTableVersion(customer.getHisVersion()); // 替换表名
            QueryWrapper<Customer> wrapper = new QueryWrapper();
            wrapper.orderByDesc("STATUS");
            wrapper.orderByAsc("ORDER_NUM");
            if (StringUtils.isNotEmpty(customer.getName())) {
                wrapper.like("NAME", customer.getName());
            }
            if (StringUtils.isNotEmpty(customer.getVersion())) {
                wrapper.eq("VERSION", customer.getVersion());
            }
            if (StringUtils.isNotEmpty(customer.getCode())) {
                wrapper.like("CODE", customer.getCode());
            }
            if (null != customer.getStatus()) {
                wrapper.eq("STATUS", customer.getStatus());
            }
            return this.list(wrapper);
        } finally {
            RequestDataHelper.removeThreadLocal();
        }
    }

    /**
     * 查询客户信息列表
     *
     * @param customer 客户信息
     * @return 客户信息
     */
    @Override
    public Customer selectCustomerById(Customer customer) {
        try {
            TableInfoUtil.handleTableVersion(customer.getHisVersion()); // 替换表名
            Customer customerNew = this.getById(customer.getId());
            this.getCustmoerInfo(customerNew);
            return customerNew;
        } finally {
            RequestDataHelper.removeThreadLocal();
        }
    }

    /**
     * 查询客户树结构信息
     *
     * @return 客户树信息集合
     */
    public List<TreeNode> selectCustomerTreeList() {
        List<TreeNode> list = new ArrayList<>();
        QueryWrapper<Customer> wrapper = new QueryWrapper<>();
        wrapper.orderByAsc("PARENT_ID,ORDER_NUM");
        wrapper.eq("STATUS", YssStatusEnum.NORMAL.getCode());
        List<Customer> listCustomer = this.list(wrapper);
        if (StringUtils.isEmpty(listCustomer)) {
            return list;
        }
        List<String> tempList = listCustomer.stream().map(Customer::getId).collect(Collectors.toList());
        Set<String> set = new HashSet<>();
        for (Customer customer : listCustomer) {
            if (set.contains(customer.getParentId()) || tempList.contains(customer.getParentId())) {
                continue;
            }
            list.addAll(this.recursionTree(customer.getParentId(), listCustomer));
            set.add(customer.getParentId());
        }
        return list;
    }

    private List<TreeNode> recursionTree(String id, List<Customer> listCustomer) {
        List<TreeNode> list = new ArrayList<>();
        for (Customer customer : listCustomer) {
            if (!id.equals(customer.getParentId())) {
                continue;
            }
            TreeNode treeNode = this.handCustomerToNode(customer);
            List<TreeNode> children = recursionTree(customer.getId(), listCustomer);
            treeNode.setChildren(children);
            list.add(treeNode);
        }
        return list;
    }

    /**
     * 将业务功能转化成TreeNode
     */
    private TreeNode handCustomerToNode(Customer customer) {
        TreeNode node = new TreeNode();
        node.setId(customer.getId());
        node.setParentId(customer.getParentId());
        node.setLabel(customer.getName());
        return node;
    }

    /**
     * 递归查询所有下级客户ID集合
     *
     * @param id
     * @return
     * @throws Exception
     */
    public List<String> queryCustomerIds(String id) {
        if (StringUtils.isBlank(id)) {
            throw new BusinessException("获取客户信息失败，请稍后重试！");
        }
        List<String> strList = new ArrayList<>();
        List<Customer> list = this.list(new QueryWrapper<>());
        recursionIds(id, strList, list);
        return strList;
    }

    private void recursionIds(String id, List<String> strList, List<Customer> list) {
        for (Customer customer : list) {
            if (!id.equals(customer.getParentId())) {
                continue;
            }
            strList.add(customer.getId());
            recursionIds(customer.getId(), strList, list);
        }
    }


    /**
     * 添加客户信息
     *
     * @param customer
     * @throws Exception
     */
    @Transactional
    public boolean addCustomer(Customer customer) {
        try {
            if (StringUtils.isNull(customer)) {
                throw new BusinessException("获取模块信息失败，请稍后重试！");
            }
            TableInfoUtil.handleTableVersion(customer.getHisVersion()); // 替换表名
            if (!this.checkNameUnique(customer)) {
                throw new BusinessException("客户名称【" + customer.getName() + "】已存在");
            }
            String id = IdUtils.fastSimpleUUID();
            customer.setId(id);
            customer.setStatus(YssStatusEnum.NORMAL.getCode());
            customer.setCreateBy(SecurityUtils.getUsername());
            customer.setCreateTime(new Date());
            if (YssYseNoEnum.YES.getCode() == customer.getIsUse()) {
                customer.setUseTime(new Date());
            }
            if (YssYseNoEnum.NO.getCode() == customer.getIsUse()) {
                customer.setLicenseDueTime(null);
            }
            this.insertData(customer);
            if ("0".equals(customer.getParentId())) {
                return this.save(customer);
            }
            //添加之前没有下级模块的数据的 添加了以后 模块的关联关系修改到下级
            // 获取该模块的上级之前是不是最明细的
            QueryWrapper<Customer> wrapper = new QueryWrapper<>();
            wrapper.eq("PARENT_ID", customer.getParentId());
            List<Customer> list = this.list(wrapper);
            if (StringUtils.isEmpty(list)) { //添加的上级以前没有下级
                // 将关联关系表中原来模块的数据，更新成现在这个新的下级菜单
                UpdateWrapper<DataCustomer> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("CUSTOMER_ID", customer.getParentId());
                DataCustomer dataCustomer = new DataCustomer();
                dataCustomer.setCustomerId(id);
                dataCustomer.setId(customer.getParentId()); //条件
                dataCustomerService.update(dataCustomer, updateWrapper);
            }
            return this.save(customer);
        } finally {
            RequestDataHelper.removeThreadLocal();
        }
    }

    /**
     * 插入关联关系表信息
     */
    private void insertData(Customer customer) {
        if (StringUtils.isNull(customer)) {
            return;
        }
        if (StringUtils.isNotEmpty(customer.getListModular())) {
            List<DataModular> list = new ArrayList<>();
            for (String modularId : customer.getListModular()) {
                DataModular dataModular = new DataModular();
                dataModular.setId(IdUtils.fastSimpleUUID());
                dataModular.setModularId(modularId);
                dataModular.setDataId(customer.getId());
                dataModular.setDataCode(ReportWorldEnum.REPORT_CUSTOMER_CODE.getCode());
                list.add(dataModular);
            }
            dataModularService.saveBatch(list);
        }
        if (StringUtils.isNotEmpty(customer.getListReport())) {
            List<DataReport> list = new ArrayList<>();
            for (String reportId : customer.getListReport()) {
                DataReport dataReport = new DataReport();
                dataReport.setId(IdUtils.fastSimpleUUID());
                dataReport.setReportId(reportId);
                dataReport.setDataId(customer.getId());
                dataReport.setDataCode(ReportWorldEnum.REPORT_CUSTOMER_CODE.getCode());
                list.add(dataReport);
            }
            dataReportService.saveBatch(list);
        }
    }

    /**
     * 修改客户信息
     *
     * @param customer
     * @throws Exception
     */
    @Transactional
    public boolean editCustomer(Customer customer) {
        try {
            if (StringUtils.isNull(customer) || StringUtils.isBlank(customer.getId())) {
                throw new BusinessException("获取模块信息失败，请稍后重试！");
            }
            TableInfoUtil.handleTableVersion(customer.getHisVersion()); // 替换表名
            if (!this.checkNameUnique(customer)) {
                throw new BusinessException("客户名称【" + customer.getName() + "】已存在");
            }
            // 修改之前的上级只有一个下级
            Customer oldCustomer = this.getById(customer.getId());
            // 之前没有启用，现在启用，存入启用时间
            if (YssYseNoEnum.NO.getCode() == oldCustomer.getIsUse() && YssYseNoEnum.YES.getCode() == customer.getIsUse()) {
                customer.setUseTime(new Date());
            }
            if (YssYseNoEnum.NO.getCode() == customer.getIsUse()) {
                customer.setLicenseDueTime(null);
            }
            QueryWrapper<Customer> wrapperOld = new QueryWrapper<>();
            wrapperOld.eq("PARENT_ID", oldCustomer.getId());
            List<Customer> listOld = this.list(wrapperOld);
            if (StringUtils.isEmpty(listOld)) { //修改之前没有下级
                QueryWrapper<Customer> wrapper = new QueryWrapper<>();
                wrapper.eq("PARENT_ID", oldCustomer.getParentId());
                List<Customer> list = this.list(wrapper);
                if (!StringUtils.isEmpty(list) && list.size() == 1) {
                    // 原来的关联表是这个明细的ID 更新成现在将会变成明细的上级ID
                    UpdateWrapper<DataCustomer> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.eq("CUSTOMER_ID", oldCustomer.getId());
                    DataCustomer dataCustomer = new DataCustomer();
                    dataCustomer.setCustomerId(oldCustomer.getParentId());
                    dataCustomer.setId(oldCustomer.getId());
                    dataCustomerService.update(dataCustomer, updateWrapper);
                }
            }
            customer.setUpdateBy(SecurityUtils.getUsername());
            customer.setUpdateTime(new Date());
            //删除关联关系重新插入
            //删除表和模块信息关联关系
            QueryWrapper<DataModular> wrapperModular = new QueryWrapper<>();
            wrapperModular.in("DATA_ID", customer.getId());
            wrapperModular.eq("DATA_CODE", ReportWorldEnum.REPORT_CUSTOMER_CODE.getCode());
            dataModularService.remove(wrapperModular);
            //删除表和报表信息关联关系
            QueryWrapper<DataReport> wrapperReport = new QueryWrapper<>();
            wrapperReport.in("DATA_ID", customer.getId());
            wrapperReport.eq("DATA_CODE", ReportWorldEnum.REPORT_CUSTOMER_CODE.getCode());
            dataReportService.remove(wrapperReport);
            this.insertData(customer);
            //修改后的上级
            if ("0".equals(customer.getParentId())) {
                return this.updateById(customer);
            }
            // 修改后的这上级 之前是否存在下级
            QueryWrapper<Customer> wrapper = new QueryWrapper<>();
            wrapper.eq("PARENT_ID", customer.getParentId());
            List<Customer> list = this.list(wrapper);
            if (StringUtils.isEmpty(list)) { //添加的上级以前没有下级
                // 将关联关系表中原来模块的数据，更新成现在这个新的下级菜单
                UpdateWrapper<DataCustomer> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("CUSTOMER_ID", customer.getParentId());
                DataCustomer dataCustomer = new DataCustomer();
                dataCustomer.setCustomerId(customer.getId());
                dataCustomer.setId(customer.getParentId());
                dataCustomerService.update(dataCustomer, updateWrapper);
            }
            return this.updateById(customer);
        } finally {
            RequestDataHelper.removeThreadLocal();
        }
    }

    /**
     * 删除客户信息
     *
     * @param customer
     * @throws Exception
     */
    public boolean delCustomer(Customer customer) {
        try {
            if (StringUtils.isBlank(customer.getId())) {
                throw new BusinessException("获取删除模块信息失败，请稍后重试！");
            }
            TableInfoUtil.handleTableVersion(customer.getHisVersion()); // 替换表名
            QueryWrapper<Customer> customerQueryWrapper1 = new QueryWrapper<>();
            customerQueryWrapper1.eq("PARENT_ID", customer.getId());
            List<Customer> list = this.list(customerQueryWrapper1);
            if (list.size() > 0) {
                throw new BusinessException("存在下级客户,不允许删除");
            }
            // List<String> list = this.queryCustomerIds(id); //所有下级模块
            Customer oldCustomer = this.getById(customer.getId());
            //删除表和模块信息关联关系
            QueryWrapper<DataModular> wrapperModular = new QueryWrapper<>();
            wrapperModular.in("DATA_ID", customer.getId());
            wrapperModular.eq("DATA_CODE", ReportWorldEnum.REPORT_CUSTOMER_CODE.getCode());
            dataModularService.remove(wrapperModular);
            //删除表和报表信息关联关系
            QueryWrapper<DataReport> wrapperReport = new QueryWrapper<>();
            wrapperReport.in("DATA_ID", customer.getId());
            wrapperReport.eq("DATA_CODE", ReportWorldEnum.REPORT_CUSTOMER_CODE.getCode());
            dataReportService.remove(wrapperReport);
            // 删除的这个ID 不是一个一级的
            if ("0".equals(oldCustomer.getParentId())) {
                // 删除关联关系表中所所有改id包括所有下级的
                QueryWrapper<DataCustomer> wrapper = new QueryWrapper<>();
                wrapper.in("CUSTOMER_ID", customer.getId());
                dataCustomerService.remove(wrapper);
                QueryWrapper<Customer> wrapperCustomer = new QueryWrapper<>();
                wrapperCustomer.eq("ID", customer.getId());
                return this.removeById(customer.getId());
            }
            UpdateWrapper<DataCustomer> updateWrapper = new UpdateWrapper<>();
            updateWrapper.in("CUSTOMER_ID", customer.getId());
            DataCustomer dataCustomer = new DataCustomer();
            dataCustomer.setCustomerId(oldCustomer.getParentId());
            dataCustomerService.update(dataCustomer, updateWrapper);
            return this.removeById(customer.getId());
        } finally {
            RequestDataHelper.removeThreadLocal();
        }
    }


    /**
     * 获取客户信息
     *
     * @return
     * @throws Exception
     */
    public Map<String, Customer> getCustomerMap() {
        Map<String, Customer> mapReportCustomer = new HashMap<>();
        List<Customer> listCustomer = list();
        if (StringUtils.isEmpty(listCustomer)) {
            return null;
        }
        for (Customer customer : listCustomer) {
            if (StringUtils.isNull(customer) || StringUtils.isBlank(customer.getId())) {
                continue;
            }
            mapReportCustomer.put(customer.getId(), customer);
        }
        return mapReportCustomer;
    }

    /**
     * 导出客户许可文件 Base64 加密  提供给升级工具使用
     */
    @Override
    public String customerBase64(Customer customer) {
        try {
            TableInfoUtil.handleTableVersion(customer.getHisVersion()); // 替换表名
            String[] includeProperties = {"id", "name", "status", "listModular", "listReport", "expireDate", "username", "password"};
            PropertyPreFilters filters = new PropertyPreFilters();
            PropertyPreFilters.MySimplePropertyPreFilter includefilter = filters.addFilter();
            includefilter.addIncludes(includeProperties);
            Customer customerInfo = this.getById(customer.getId());
            if (StringUtils.isNull(customerInfo)) {
                throw new BusinessException("没有获取到客户信息，请稍后重试！");
            }
            //许可到期时间
            customerInfo.setExpireDate(DateUtils.addYear(DateUtils.dateToStr(customerInfo.getLicenseDueTime()), 1));
            // 默认用户名密码
            customerInfo.setUsername(ReportWorldEnum.USERNAME.getDesc());
            customerInfo.setPassword(ReportWorldEnum.PASSWORD.getDesc());
            this.getCustmoerInfo(customerInfo);
            String jsonCustomer = JSONObject.toJSONString(customerInfo, includefilter, SerializerFeature.WriteMapNullValue);
            // 使用基本型的编码器和解码器 对数据进行编码和解码
            //1.获取编码器
            Base64.Encoder encoder = Base64.getEncoder();
            //2.对字符串进行编码
            String strCustomer = encoder.encodeToString(jsonCustomer.getBytes());
            //4.获取解码器
            //  Base64.Decoder decoder = Base64.getDecoder();
            //5.对编码后的字符串进行解码
            //  byte[] decode = decoder.decode(strCustomer);
            //  String s1 = new String(decode);
            //  log.info("解码后的字符串："+s1);
            return strCustomer;
        } finally {
            RequestDataHelper.removeThreadLocal();
        }
    }

    /**
     * 获取客户的模块和报表信息
     *
     * @param customer
     */
    private void getCustmoerInfo(Customer customer) {
        if (StringUtils.isNull(customer) || StringUtils.isEmpty(customer.getId())) {
            return;
        }
        //获取客户的模块信息关联关系
        QueryWrapper<DataModular> wrapperModular = new QueryWrapper<>();
        wrapperModular.in("DATA_ID", customer.getId());
        wrapperModular.eq("DATA_CODE", ReportWorldEnum.REPORT_CUSTOMER_CODE.getCode());
        List<DataModular> dataModulars = dataModularService.list(wrapperModular);
        if (StringUtils.isNotEmpty(dataModulars)) {
            List<String> listModular = new ArrayList<>();
            for (DataModular dataModular : dataModulars) {
                if (StringUtils.isNull(dataModular) || StringUtils.isEmpty(dataModular.getModularId())) {
                    continue;
                }
                listModular.add(dataModular.getModularId());
            }
            customer.setListModular(listModular);
        }
        //获取客户的报表信息关联关系
        QueryWrapper<DataReport> wrapperReport = new QueryWrapper<>();
        wrapperReport.in("DATA_ID", customer.getId());
        wrapperReport.eq("DATA_CODE", ReportWorldEnum.REPORT_CUSTOMER_CODE.getCode());
        List<DataReport> dataReports = dataReportService.list(wrapperReport);
        if (StringUtils.isNotEmpty(dataModulars)) {
            List<String> listReport = new ArrayList<>();
            for (DataReport dataReport : dataReports) {
                if (StringUtils.isNull(dataReport) || StringUtils.isEmpty(dataReport.getReportId())) {
                    continue;
                }
                listReport.add(dataReport.getReportId());
            }
            customer.setListReport(listReport);
        }
    }

    /**
     * 校验客户名称是否唯一
     *
     * @param customer
     * @return 结果
     */
    private boolean checkNameUnique(Customer customer) {
        TableInfoUtil.handleTableVersion(customer.getHisVersion()); // 替换表名
        String customerId = StringUtils.isNull(customer.getId()) ? "-1" : customer.getId();
        QueryWrapper<Customer> wrapper = new QueryWrapper<>();
        wrapper.eq("NAME", customer.getName());
        wrapper.eq("PARENT_ID", customer.getParentId());
        Customer info = this.getOne(wrapper);
        if (StringUtils.isNotNull(info) && !info.getId().equals(customerId)) {
            return false;
        }
        return true;
    }

    /**
     * 查询客户许可到期时间
     * 许可还有一个月到期提示一次，
     * 剩余3天，每天提示
     *
     * @return
     */
    public String queryLicenseDueTime() {
        List<Customer> list = this.list();
        if (StringUtils.isEmpty(list)) {
            return null;
        }
        StringBuffer buffer = new StringBuffer();
        for (Customer customer : list) {
            // 没有使用和到期日期为空的不提示
            if (YssYseNoEnum.NO.getCode() == customer.getIsUse() || StringUtils.isNull(customer.getLicenseDueTime())) {
                continue;
            }
            if (DateUtils.differentDaysByDate(new Date(), customer.getLicenseDueTime()) == 30) {
                buffer.append("客户【").append(customer.getName() + "】的许可还有30天到期，请注意更新许可到期日期！").append("\r\n");
            }
            if (DateUtils.differentDaysByDate(new Date(), customer.getLicenseDueTime()) <= 3) {
                buffer.append("客户【").append(customer.getName() + "】的许可剩余时间不不足三天，请注意更新许可到期日期！").append("\r\n");
            }
            if (DateUtils.differentDaysByDate(new Date(), customer.getLicenseDueTime()) < 0) {
                buffer.append("客户【").append(customer.getName() + "】的许可已过期，请注意更新许可到期日期！").append("\r\n");
            }
        }
        // 发送企业微信
        if (StringUtils.isNotEmpty(buffer.toString())) {
            weComService.sendMessageToManage(buffer.toString());
        }
        return buffer.toString();
    }


}
